#include <program.h>
#include <stdio.h>
#include <string.h>

Program::Program()
: id(0)
, linked(0)
, log(NULL)
{

}

Program::~Program()
{
	if (id > 0)
		glDeleteProgram(id);

	if (log != NULL)
	{
		delete [] log;
		log = NULL;
	}
}

void Program::load(GLuint vertexShader, GLuint fragmentShader)
{
	id = glCreateProgram();

	if (id != 0)
	{
		glAttachShader(id, vertexShader);		
		glAttachShader(id, fragmentShader);
	}

	glLinkProgram(id);
	glGetProgramiv(id, GL_LINK_STATUS, &linked);

	if (!linked)
	{
		GLint infoLen = 0;
		glGetProgramiv(id, GL_INFO_LOG_LENGTH, &infoLen);

		if (infoLen > 1)
		{
			if (log == NULL)
				log = new char[infoLen];

			glGetProgramInfoLog(id, infoLen, NULL, log);
		}
		glDeleteProgram(id);

		//TODO Must free shaders
	}
}
void Program::addShaderIO(const char* io_name, io_type type)
{
	switch(type)
	{
		case IO_TYPE_ATTRIBUTE:
		{
			GLint attr = glGetAttribLocation(id, io_name);
			shaders_io.insert(std::pair<const char *, GLint>(io_name, attr));
		}
		break;
		case IO_TYPE_UNIFORM:
		{
			GLint unif = glGetUniformLocation(id, io_name);
			shaders_io.insert(std::pair<const char *, GLint>(io_name, unif));
		}
		break;
	}
}

GLint Program::getShaderIO(const char* io_string)
{
	// return shaders_io[io_string];
	std::map<const char *, GLint>::iterator it;
	for (it=shaders_io.begin(); it!=shaders_io.end(); ++it)
	{
		if (strcmp(io_string, it->first) == 0)
		{
			return it->second;
		}
	}
	return -1;
}

void Program::use()
{
	if (id > 0)
		glUseProgram(id);
}
